//
// Created by haoy on 2017/4/29.
//

#ifndef RTC_XSWITCH2_RTPHEADER_HPP
#define RTC_XSWITCH2_RTPHEADER_HPP

#include <arpa/inet.h>
#include <cstdint>

namespace benchmark {

//    0                   1                   2                   3
//    0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
//   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
//   |V=2|P|X|  CC   |M|     PT      |       sequence number         |
//   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
//   |                           timestamp                           |
//   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
//   |           synchronization source (SSRC) identifier            |
//   +=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+
//   |            contributing source (CSRC) identifiers             |
//   |                             ....                              |
//   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+


// 0                   1                   2                   3
//  0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
// |      defined by profile       |           length              |
// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
// |                        header extension                       |
// |                             ....                              |

class RtpHeader {
public:
    static const int MIN_SIZE = 12;
    uint32_t cc :4;
    uint32_t hasextension :1;
    uint32_t padding :1;
    uint32_t version :2;
    uint32_t payloadtype :7;
    uint32_t marker :1;
    uint32_t seqnum :16;
    uint32_t timestamp;
    uint32_t ssrc;
    uint32_t extensionpayload:16;
    uint32_t extensionlength:16;
    /*    RFC 5285
        0                   1                   2                   3
       0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
      +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
      |       0xBE    |    0xDE       |           length=3            |
      +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
      |  ID   | L=0   |     data      |  ID   |  L=1  |   data...
      +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
            ...data   |    0 (pad)    |    0 (pad)    |  ID   | L=3   |
      +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
      |                          data                                 |
      +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+

    */
    uint32_t extensions;

    inline RtpHeader() :
            cc(0), hasextension(0), padding(0), version(2), payloadtype(0), marker(
            0), seqnum(0), timestamp(0), ssrc(0), extensionpayload(0), extensionlength(0) {
        // No implementation required
    }

    inline uint8_t hasPadding() const {
        return padding;
    }

    inline void setPadding(uint8_t has_padding) {
        padding = has_padding;
    }

    inline uint8_t getVersion() const {
        return version;
    }
    inline void setVersion(uint8_t aVersion) {
        version = aVersion;
    }
    inline uint8_t getMarker() const {
        return marker;
    }
    inline void setMarker(uint8_t aMarker) {
        marker = aMarker;
    }
    inline uint8_t getExtension() const {
        return hasextension;
    }
    inline void setExtension(uint8_t ext) {
        hasextension = ext;
    }
    inline uint8_t getCc() const {
        return cc;
    }
    inline void setCc(uint8_t theCc) {
        cc = theCc;
    }
    inline uint8_t getPayloadType() const {
        return payloadtype;
    }
    inline void setPayloadType(uint8_t aType) {
        payloadtype = aType;
    }
    inline uint16_t getSeqNumber() const {
        return ntohs(seqnum);
    }
    inline void setSeqNumber(uint16_t aSeqNumber) {
        seqnum = htons(aSeqNumber);
    }
    inline uint32_t getTimestamp() const {
        return ntohl(timestamp);
    }
    inline void setTimestamp(uint32_t aTimestamp) {
        timestamp = htonl(aTimestamp);
    }
    inline uint32_t getSSRC() const {
        return ntohl(ssrc);
    }
    inline void setSSRC(uint32_t aSSRC) {
        ssrc = htonl(aSSRC);
    }
    inline uint16_t getExtId() const {
        return ntohs(extensionpayload);
    }
    inline void setExtId(uint16_t extensionId) {
        extensionpayload = htons(extensionId);
    }
    inline uint16_t getExtLength() const {
        return ntohs(extensionlength);
    }
    inline void setExtLength(uint16_t extensionLength) {
        extensionlength = htons(extensionLength);
    }
    inline int getHeaderLength() const {
        return MIN_SIZE + cc * 4; //+ (hasextension ? (4 + ntohs(extensionlength) * 4) : 0)
    }
};

}


#endif //RTC_XSWITCH2_RTPHEADER_HPP
